package com.winit.jumpServer.manager;

import com.winit.common.base.beans.LoginUser;
import com.winit.common.util.*;
import com.winit.deploy.manager.DeployManager;
import com.winit.jumpServer.bean.JumpServerInfo;
import com.winit.jumpServer.bean.PushRecordInfo;
import com.winit.jumpServer.task.PushTask;
import com.winit.jumpServer.util.JumpServerListInfo;
import com.winit.project.core.bean.ProjectInfo;
import com.winit.project.service.ProjectService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;

import javax.annotation.Resource;
import java.util.*;

/**
 * 推送
 * Created by wangjian on 16/4/5.
 */
@Component
public class PushRecordManager {

    static final Logger logger = LoggerFactory.getLogger(PushRecordManager.class);

    @Resource(name = "taskExecutor")
    private ThreadPoolTaskExecutor taskExecutor;
    @Autowired
    private ProjectService projectService;
    @Resource
    private DeployManager deployManager;

    /**
     * 获取推送记录信息列表
     *
     * @return
     */
    public List<PushRecordInfo> getPushRecordList() {
        List<PushRecordInfo> list = new ArrayList<PushRecordInfo>();
        StringBuffer path = new StringBuffer();
        path.append(ConfigUtil.getValue("rootPath")).append("Beetle/pushRecord");
        String[] param = ShellRunUtil.getListParam(path.toString());
        String str = ShellRunUtil.runShell(param);
        if (StringUtils.isEmpty(str) || ",".equals(str)) {
            return list;
        }

        String[] records = str.split(",");
        for (String record : records) {
            if (StringUtils.isEmpty(record)) {
                continue;
            }
            PushRecordInfo info = this.getPushRecordInfo(record);
            if (info == null) {
                continue;
            }
            list.add(info);
        }
        return list;

    }

    /**
     * 获取推送记录信息
     *
     * @param recordName
     * @return
     */
    public PushRecordInfo getPushRecordInfo(String recordName) {
        StringBuffer path = new StringBuffer();
        path.append(ConfigUtil.getValue("rootPath")).append("Beetle/pushRecord/").append(recordName).append("/record-info.json");
        PushRecordInfo info = JSONFileUtil.getFileJsonForBean(path.toString(), PushRecordInfo.class);
        logger.info("获取推送记录信息,info=" + ObjectToString.getString(info));
        return info;
    }

    /**
     * 新推送记录,推送工程相关的所有跳板机
     * 版本测试通过后自动推送
     * 版本测试通过后,不管有没有配置跳板机,都进行推送
     *
     * @param projectName
     * @param editionNum
     * @param loginUser
     * @return
     */
    public boolean createPush(String projectName, String editionNum, boolean testPass, LoginUser loginUser) throws Exception {
        LogUtil.operateLog(loginUser, projectName, editionNum, "", LogUtil.OperateType.CREATE_PUSH_RECORD);
        ProjectInfo projectInfo = projectService.getProjectInfo(projectName);
        if (projectInfo == null) {
            return false;
        }
        List<String> levelOneList = new ArrayList<String>();
        List<String> levelTwoList = new ArrayList<String>();
        for (String key : JumpServerListInfo.jumpServerInfo.keySet()) {
            JumpServerInfo info = JumpServerListInfo.jumpServerInfo.get(key);
            if (Constants.JUMPSERVER_LEVELL_1.equals(info.getLevel())) {
                if (levelOneList.contains(key)) {
                    continue;
                }
                levelOneList.add(key);
            } else if (Constants.JUMPSERVER_LEVELL_2.equals(info.getLevel())) {
                if (levelTwoList.contains(key)) {
                    continue;
                }
                levelTwoList.add(key);
            }
        }

        for (String ip : levelTwoList) {
            JumpServerInfo jumpServerInfo = JumpServerListInfo.jumpServerInfo.get(ip);
            if (jumpServerInfo == null) {
                continue;
            }
            this.createPushInfo(projectName, editionNum, jumpServerInfo, testPass, loginUser);
            levelOneList.remove(jumpServerInfo.getParentIp());
        }
        for (String ip : levelOneList) {
            JumpServerInfo jumpServerInfo = JumpServerListInfo.jumpServerInfo.get(ip);
            if (jumpServerInfo == null) {
                continue;
            }
            this.createPushInfo(projectName, editionNum, jumpServerInfo, testPass, loginUser);
        }

        return true;
    }

    /**
     * 新推送记录
     *
     * @param projectName
     * @param editionNum
     * @return
     */
    private boolean createPushInfo(String projectName, String editionNum, JumpServerInfo jumpServerInfo, boolean testPass, LoginUser loginUser) {
        logger.info("生成新推送记录");
        Date now = new Date();

        String strCurDate = DateUtil.formatDate(now, "yyyyMMddHHmmss");

        String rd = SeqGenerate.getSeqId(Constants.PUSH_THREAD_INDEX, "3");
        StringBuffer recordName = new StringBuffer();
        recordName.append(strCurDate).append(rd);

        PushRecordInfo info = new PushRecordInfo();
        info.setCreateTime(DateUtil.formatDate(now, "yyyy-MM-dd HH:mm:ss"));
        info.setOperator(loginUser.getUserName());
        info.setProjectName(projectName);
//        info.setEnvName(envName);
        info.setEditionNum(editionNum);
//        String jumpServerIp = jumpServerManager.getJumpServerIpForProject(projectName);
        info.setJumpServerIp(jumpServerInfo.getIp());
        info.setStatus(Constants.JUMPSERVER_PUSH_STATUS_STOP);
        info.setDesc("");
        info.setRecordName(recordName.toString());

        if (StringUtils.isEmpty(jumpServerInfo.getParentIp())) {
            info.setPushFrom(Constants.JUMPSERVER_PUSH_FROM_DEFULT);
        } else {
            info.setPushFrom(jumpServerInfo.getParentIp());
        }

        StringBuffer path = new StringBuffer();
        path.append(ConfigUtil.getValue("rootPath")).append("Beetle/pushRecord/").append(recordName.toString());

        String[] param = ShellRunUtil.createFileParam(path.toString());
        String str = ShellRunUtil.runShell(param);
        if (!StringUtils.isEmpty(str) && !(",".equals(str))) {
            logger.info("创建推送记录,生成文件夹失败,path=" + path);
            return false;
        }

        path.append("/record-info.json");

        boolean flag = JSONFileUtil.saveFileJson(path.toString(), info);
        logger.info("保存推送信息,flag=" + flag + ",info=" + ObjectToString.getString(info));
        //保存文件成功后,启动推送线程
        if (flag) {
            cachePushTask(info.getProjectName(),info.getJumpServerIp());
            PushTask task = new PushTask(info, testPass, deployManager, loginUser);
            LogUtil.echoThreadCount(logger, taskExecutor, "taskExecutor,推送任务");
            taskExecutor.execute(task);
        }

        return flag;
    }

    public synchronized void cachePushTask(String projectName, String ip) {
        List<String> list = JumpServerListInfo.pushTaskList.get(projectName);
        if (list == null) {
            list = new ArrayList<>();
        }
        list.add(ip);
        JumpServerListInfo.pushTaskList.put(projectName, list);
    }

    /**
     * 重新推送
     *
     * @param recordName
     * @return
     */
    public Map<String, Object> rePush(String recordName, LoginUser loginUser) {
        logger.info("重新推送,生成推送记录");
        Map<String, Object> rtnMap = new HashMap<String, Object>();
        Date now = new Date();
        StringBuffer path = new StringBuffer();
        path.append(ConfigUtil.getValue("rootPath")).append("Beetle/pushRecord/").append(recordName).append("/record-info.json");

        PushRecordInfo info = JSONFileUtil.getFileJsonForBean(path.toString(), PushRecordInfo.class);

        LogUtil.operateLog(loginUser, info.getProjectName(), info.getEditionNum(), "", LogUtil.OperateType.RE_PUSH);

        String strCurDate = DateUtil.formatDate(now, "yyyyMMddHHmmss");

        String rd = SeqGenerate.getSeqId(Constants.PUSH_THREAD_INDEX, "3");
        StringBuffer name = new StringBuffer();
        name.append(strCurDate).append(rd);

        info.setCreateTime(DateUtil.formatDate(now, "yyyy-MM-dd HH:mm:ss"));
        info.setOperator(loginUser.getUserName());
//        String jumpServerIp = jumpServerManager.getJumpServerIpForProject(info.getProjectName(),info.getEnvName()).get(0);
//        info.setJumpServerIp(jumpServerIp);
        info.setStatus(Constants.JUMPSERVER_PUSH_STATUS_STOP);
        info.setDesc("");
        info.setRecordName(name.toString());

        StringBuffer newPath = new StringBuffer();
        newPath.append(ConfigUtil.getValue("rootPath")).append("Beetle/pushRecord/").append(info.getRecordName());

        String[] param = ShellRunUtil.createFileParam(newPath.toString());
        String str = ShellRunUtil.runShell(param);
        if (!StringUtils.isEmpty(str) && !(",".equals(str))) {
            logger.info("创建推送记录,生成文件夹失败,path=" + newPath);
            rtnMap.put("code", "1");
            rtnMap.put("desc", "生成推送记录,生成文件夹失败!");
            return rtnMap;
        }

        newPath.append("/record-info.json");

        boolean flag = JSONFileUtil.saveFileJson(newPath.toString(), info);
        logger.info("保存推送信息,flag=" + flag + ",info=" + ObjectToString.getString(info));
        //保存文件成功后,启动推送线程
        if (flag) {
            cachePushTask(info.getProjectName(),info.getJumpServerIp());
            PushTask task = new PushTask(info, false);
            LogUtil.echoThreadCount(logger, taskExecutor, "taskExecutor,推送任务");
            taskExecutor.execute(task);
            rtnMap.put("code", "0");
            rtnMap.put("desc", "生成推送记录成功");
            return rtnMap;
        } else {
            rtnMap.put("code", "1");
            rtnMap.put("desc", "生成推送记录,保存推送信息失败");
            return rtnMap;
        }
    }

}
